package com.bjtu.transactionclient.core;

import com.bjtu.transactionclient.base.result.Result;
import com.bjtu.transactionclient.base.result.SuccessEnum;
import com.bjtu.transactionclient.dao.UserIndexDao;
import com.bjtu.transactionclient.domain.SendSqlData;
import com.bjtu.transactionclient.domain.UserIndexNoTable;
import com.bjtu.transactionclient.service.IndexServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.sql.SQLData;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

//数据库不一致性的诱导性因素
@Service("Judger")
public class ConflictProcessor {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    private UserIndexDao userIndexDao;

    private synchronized void executeSql(List<SendSqlData> sql) {
        for (SendSqlData sendData:sql) {
            System.out.println("sql:"+sendData.getSql());
            try {
                jdbcTemplate.update(sendData.getSql());
                writeToSql(sendData.getSql());
            }catch (Exception e) {
                if (e instanceof DuplicateKeyException) {//捕获主键重复异常，主要用于没有indexNo的表中的插入
                    String tableName = sendData.getSql().split(" ")[2];
                    //String id = sendData.getKeyInfo().split("=")[0];
                    String selectsql = " select count(*) from " + tableName;
                    String size = jdbcTemplate.queryForObject(selectsql, java.lang.String.class);
                    int keyValue = Integer.valueOf(size) + 1;
                    String keyorigin = sendData.getKeyInfo().split("\"")[1];
                    String s = sendData.getSql().replace(keyorigin, String.valueOf(keyValue));
                    jdbcTemplate.update(s);
                    writeToSql(s);
                }
            }
        }
    }

    /*
     * 保存到txt的格式：sql语句;主键
     *
     */
    private void writeToSql(String sendSqlData) {
        //我们不记录userupdateofverisonandtables表
        if(sendSqlData.contains("userupdateofverisonandtables"))
            return;
        BufferedWriter writer = null;
        try {
            File file = ResourceUtils.getFile("Status.txt");
            //File file = new File(ClassLoader.getSystemResource("canalsql.txt").toURI());
            writer  = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true), "UTF-8"));
            writer.append(sendSqlData+";"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            writer.append("\r\n");
            writer.flush();
            writer.close();
        } catch(FileNotFoundException e) {
            System.out.println("File Not Found");
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Autowired
    private IndexServiceImpl service;
    //YN型操作
    //有共同的索引号，但是内容不同
    public  void ProcessYN(String rankA, String rankB, int operationB, List<SendSqlData> sqls ,List<Result> results)
    {
        //不含insert，代表修改内容过大，这时先执行请求方的修改
        if(!isIncludeInsert(sqls))
        executeSql(sqls);
        else {
            //含有insert,代表索引号确实产生冲突，在操作逆模型中，改变请求方的索引号执行即可
            Iterator<SendSqlData> it = sqls.iterator();
            String indexNo = sqls.get(0).getIndexNo();
            String newIndexNo = generateNewIndexNo(sqls.get(0).getIndexNo());
            while (it.hasNext()) {
                SendSqlData sqlData = it.next();
                sqlData.setSql(sqlData.getSql().replace(indexNo, newIndexNo));
//                if (sqlData.getTableName().equals("userindexnotable")) {
//                    //返回给客户端的信息，并让客户端执行修改，只需返回userindexnotable的sql语句
//                    results.add(Result.success(sqlData.getSql(), SuccessEnum.USERINDEXNO_NEW));
//                }
            }
            executeSql(sqls);
        }
    }

    //NY型操作
    //索引号不同，但内容相同.直接改变请求方的索引号,在操作逆模型中，不需要进行任何操作.
    public void ProcessNY(String rankA,String rankB,int operationB,List<SendSqlData> sqls,List<Result> results)
    {
        return;
    }

    private synchronized String generateNewIndexNo(String indexNo) {
        String prefix = indexNo.substring(0,indexNo.length()-1) + '%';
        char code = indexNo.charAt(indexNo.length()-1);
        List<String> indexNoList =  userIndexDao.queryUserIndexNoLike(prefix);
        for (String index : indexNoList) {
            char lastChar = index.charAt(index.length()-1);//取最后一个字符
            if (lastChar<code) continue;
            else if (lastChar==code) code++;
            else if (lastChar>code) break;
        }

        return prefix.substring(0,prefix.length()-1)+code;
    }

    private boolean isIncludeInsert(List<SendSqlData> sqls)
    {
        for(SendSqlData sql:sqls)
        {
            if(sql.getOperation().equals("INSERT"))
                return true;
        }
        return false;
    }


//    public String ProcessYN(String userA, String indexNo)
//    {
//        //上一次的用户
//        UserIndexNoTable uB=service.queryUserIndexNo(indexNo);
//        if(uB.getStatus() == 1)
//        { //CC型
//            String roleA= service.getRole(userA);
//            String roleB= service.getRole(uB.getUserNo());
//            if(roleA.compareTo(roleB)<0)
//            {
//                //H 型
//                return "3-2-1-1";
//            }
//            //L型
//            else if(roleA.compareTo(roleB)>0)
//            {
//                return "1-2-1-1";
//            }
//            else
//            //E型
//            {
//                return "2-2-1-1";
//            }
//        }
//        else
//        { //CM型
//            String roleA = service.getRole(userA);
//            String roleB = service.getRole(uB.getUserNo());
//            if(roleA.compareTo(roleB)<0)
//            {
//                //H 型
//                return "3-2-1-2";
//            }
//            //L型
//            else if(roleA.compareTo(roleB)>0)
//            {
//                return "1-2-1-2";
//            }
//            else
//            //E型
//            {
//                return "2-2-1-2";
//            }
//        }
//    }
//
//    //M_
//    public String ProcessNY(String userA,String indexNo)
//    {
//        //上一次的用户
//        UserIndexNoTable uB=service.queryUserIndexNo(indexNo);
//        if(uB.getStatus() == 1)
//        { //MC型
//            String roleA= service.getRole(userA);
//            String roleB= service.getRole(uB.getUserNo());
//            if(roleA.compareTo(roleB)<0)
//            {
//                //H 型
//                return "3-2-1-3";
//            }
//            //L型
//            else if(roleA.compareTo(roleB)>0)
//            {
//                return "1-2-1-3";
//            }
//            else
//            //E型
//            {
//                return "2-2-1-3";
//            }
//        }
//        else
//        { //MM型
//            String roleA = service.getRole(userA);
//            String roleB = service.getRole(uB.getUserNo());
//            if(roleA.compareTo(roleB)<0)
//            {
//                //H 型
//                return "3-2-1-4";
//            }
//            //L型
//            else if(roleA.compareTo(roleB)>0)
//            {
//                return "1-2-1-4";
//            }
//            else
//            //E型
//            {
//                return "2-2-1-4";
//            }
//        }
//    }
}